The Mets ended a four-game losing streak and won for just the third time in 12 contests.
New York trailed 2-1 when it came to bat in the sixth and Eric Young opened the rally with a double off Brad Hand (0-1), who made his fourth start of the year and the 14th of his career.
Hand retired the next two batters, but Andrew Brown drew a walk and Duda then launched a 2-2 pitch to right to put the Mets in front. It was his 13th of the season, two short of his career high established in 2011.
Giancarlo Stanton homered in the seventh to bring the Marlins within one, but Pedro Feliciano came in with a runner on base and got the Mets out of the eighth. LaTroy Hawkins then turned in a perfect ninth for his ninth save.
The win went to starter Jonathan Niese (7-7), who allowed three runs on six hits in 6 1/3.
Miami moved within eight losses of having 100 for the season.