Mathias Frank (BMC) led going into the final stage with a 13 advantage over the Portuguese rider but could not defend the yellow jersey.
He struggled on the last 9km of the mountainous TT as he finished with a time of 53:52 to finish 5th overall - some 1:56 slower than Costa's time of 51:56.
Tanel Kangert (Astana) was second against the clock 21 seconds down with Bauke Mollema (Blanco) a further eight seconds slower.
Costa beat maturing Dutchman Mollema by one minute two seconds in the final standings and Czech Roman Kreuziger by 1:10, while Frenchman Thibaut Pinot was fourth.
"It's great to win. This was an important stage and it was great to have a chance to win again.
"It was a perfect day for me. My directeur sportif gave me good time checks and I felt good in the time trial," Costa said after the win.
Before adding: "To win the Tour de Suisse once is good, to win it twice is even better and I won two stages too. It's nice to see so many fans here too."
Costa rode a quick flat time but it was in the final mountainous 9km – having switched to a road bike – that he powered to the second stage win and the overall victory.
"The bike change was fast and I kept a constant pace because I knew it was crucial to stay on my own rhythm, from the foot to the top of the climb. At the hardest slopes, I already knew the GC was really close as well as the stage, so I went full gas and made the difference," he added.
Despite his victory, the 26-year-old is not rated as a genuine threat for the 100th edition of the Tour de France starting later this month, because the all-rounder is yet to prove he has the lasting power for a three-week race.
Costa finished 18th in the Tour last year, two places ahead of Movistar team leader Alejandro Valverde.
1. Rui Costa (Movistar) 51:56"
2. Tanel Kangert (Astana) +21"
3. Bauke Mollema (Blanco) +29"
4. Jean-Christophe Peraud (AG2R) +42"
5. Andrey Amador (Movistar) +43"
6. Thibaut Pinot (FDJ) +55"
7. Roman Kreuziger (Saxo - Tinkoff) +1:00"
8. Simon Spilak (Katusha) +1:05"
9. Janez Brajkovic (Astana) +1:06"
10. Tejay Van Garderen (BMC) +1:19"
1. Rui Costa (Movistar) 31:08:11"
2. Bauke Mollema (Blanco) +1:02"
3. Roman Kreuziger (Saxo - Tinkoff) +1:10"
4. Thibaut Pinot (FDJ) +1:26"
5. Mathias Frank (BMC Racing) +1:43"
6. Tanel Kangert (Astana) +1:51"
7. Tejay Van Garderen (BMC) +2:23"
8. Daniel Martin (Garmin) +2:42"
9. Simon Spilak (Katusha) +2:42"
10. Cameron Meyer (Orica) +3:44"