T.J. Yates, who missed six weeks with a broken ankle, combined for six total touchdowns. Yates completed a career high five touchdown passes and ran for a score as well.
Brooks Foster caught four passes for 106 yards and had the biggest play of the day, a 57-yard touchdown pass from Yates to break the game open.
Yates dueled Duke's Thaddeus Lewis who returned from injury to complete 24 of 29 passes for 318 yards and three touchdowns.
Neither team could establish a consistent rush offense, leading to a combined 600 passing yards between the two starting quarterbacks.
The Heels led 14-3 early after two long drives, but Duke pulled within four after a 10-yard touchdown pass to Austin Kelly.
Yates responded with a 16-yard touchdown pass, setting up a 21-10 lead with under a minute left in the first half. Duke kicked a field goal to come within eight as the half expired.
Hakeem Nicks, who caught 5 passes for 76 yards, became UNC's first 1,000 yard receiver in a single season on a 12-yard screen that pushed the Heels' lead to 15 at the beginning of the second half.
Lewis responded, completing six passes, including a 17 yard pass to Tielor Robinson that brought Duke back within eight points. Carolina led 28-20.
Both offenses stalled until midway through the fourth quarter when Brooks Foster extended the Heels' lead to 15 points.
Carolina stopped Duke on the next possession, and Shaughn Draughn and Ryan Houston rushed for 45 yards before Yates completed his second touchdown pass to Nicks, which sealed the game for Carolina.
Duke scored on their next drive, completed the two-point conversion and recovered an onside kick, but the Heels hung on to win 42-28.