Если коротко, то setTimeout срабатывает уже после того как цикл закончился. Даже если вы укажете setTimeout (func, 0 ) всё равно выполнится только после цикла, независимо от времени работы цикла.
К этому моменту i будет равно 4 т.к. используя var переменная будет объявлена только 1 раз. Тоже самое что :
var i;
for (i = 0; i < array.length; i++)
Используя let для каждой итерации будет создаваться отдельная переменная с разным значением.