The Argentine took the first set 6-4 before the world No 1, who had won his first 17 matches of the year coming into the match, clinched an incredibly close second-set tie break 10-8.
But Del Potro kept his nerve in a thrilling climax to dominate the final-set breaker, winning it 7-2.
It denied Federer a record sixth title in Indian Wells and gave the Argentine, who had to save three match points, his first ATP Masters 1000 title.
'Looking very sharp!' - Federer helps Nadal with his suit at Laver Cup in 2019
"I'm still shaking I'm so nervous. It's difficult to describe with words, it's like a dream," del Potro said on court after extending his own winning streak to 11 matches.
"I've been working hard to get this, and I did it after all my problems, all my surgeries. I can't believe I'm here and winning a Masters 1000, beating Roger. It's amazing."
Beating Federer has never been easy - del Potro had succeeded just six times in 24 previous attempts - and the nailbiting final lasted almost three hours with both players taking occasional issue with the chair umpire.
Del Potro arrived in the Californian desert on the back of a title win in Acapulco but had far from a smooth ride against an agitated Federer, who simply would not give up on his quest for a sixth Indian Wells title.
The Argentine seized the opening set and had a match point in the second set tie break but misfired on a forehand - usually his most dependable weapon - to allow the 36-year-old Swiss back into the match.
"I was thinking about (that) forehand miss the entire time," del Potro said.
With Federer on top 6-5 in the second set tie break, he appeared to fire an ace to clinch the set, but a late challenge by del Potro overturned the call and the Swiss was double faulted.
An annoyed Federer barked at the umpire during a changeover and, fired up by his grievance, took the second set to even up the contest before pushing del Potro to the limits in the final stanza.
The third set went with serve until Federer blasted a cross-court winner to break del Potro's serve and take a 5-4 advantage - breaking a run of 32 consecutive service game wins for the Argentine.
The Swiss maestro served for the set, and the title, but del Potro dug deep to save three match points, two at 40-15 down, before breaking back to send the stanza to a tiebreak, which the Argentine dominated.
"I lost my serve a little bit, and then he was clean and I wasn't. And then it goes very quickly in the breaker," Federer said.
"As close as it can be sometimes when you're not feeling it or momentum has shifted, it's just crazy how it can go the other way."
‘Keep the points under five shots!’ - The time Nadal coached Federer at Laver Cup
'Don't be scared!' - Federer coaches Tsitsipas at Laver Cup 2019