A Cardinals loss would have clinched the division for Cincinnati. The Reds were idle, and their magic number remained at one going into Tuesday night's home game against Houston.
Holliday made it 4-all with his 28th homer, a two-run shot in the sixth inning.
St. Louis scored the go-ahead run in the seventh on a two-out throwing error by shortstop Ronny Cedeno. Matt Pagnozzi, who had three hits, came in when Cedeno threw wildly to first on a grounder by Allen Craig.
Albert Pujols had two hits and got his NL-leading 117th RBI with a single in the third.
Pedro Alvarez homered in going 3 for 3 and driving in two runs for the Pirates. He connected in the second and extended his hitting streak to seven games, during which he's 13 for 27 with 15 RBIs.
Dennys Reyes (3-1) picked up the win with one scoreless inning in relief of starter Kyle Lohse, who allowed 10 hits and four runs in six innings. Kyle McClellan got his second save in three chances with a scoreless ninth.
Notes: Former St. Louis Rams WR Isaac Bruce threw out the first pitch on Monday. ... Morton got his first hit of the season, a single up the middle in the sixth inning. He was 0 for 23. ... Holliday leads the NL with 50 two-out RBI. ... The Cardinals are 46-49 against teams under .500. ... The Pirates fell to 15-60 on the road.