See the question and my original answer on StackOverflow

What's very costy is the resizing of the image because it's a big image (you also have an extra clone before resize that seems useless and costs like ~10%).

I'm not sure you can find a faster loader / resizer, maybe irfan view wrote one specifically (TIF like the one in your sample is a simple 1 bpp B&W image. Once the image loaded, you could resize in a multithreaded mode, spawning say 2,4,8 or 16 worker threads, each one on a rectangle portion of the image, and divide overall by the number of threads).

W/o any 3rd party, here is pure .NET a sample that works in your environment, with a specific multi-threaded SizedTifImage utility class that caches all frames already resized in memory. When you run it, you will only see the initial ~1s load time and then browsing through images shouldn't be noticeable:

public partial class Form1 : Form
{
    SizedTifImage _tif;

    private void btn_Open_Click(object sender, EventArgs e)
    {
       ...
        _tif = new SizedTifImage(@"Large_Tif_Image_15pages.tif", pictureBox1.Width, pictureBox1.Height);
        pictureBox1.Image = _tif.GetFrame(0);
        btn_Next_Click(null, null);
    }

    private void btn_Next_Click(object sender, EventArgs e)
    {
        counter++;
        if (counter >= _tif.FrameCount)
        {
            counter = _tif.FrameCount - 1;
            btn_Next.Enabled = false;
        }
        btn_Next.Enabled = false;
        LoadPage();
        btn_Next.Enabled = true;
    }

    private void LoadPage()
    {
        StartWatch();
        pictureBox1.Image = _tif.GetFrame(counter);
        Stopwatch();
    }
}

public class SizedTifImage : IDisposable
{
    private Image _image;
    private ConcurrentDictionary<int, Image> _frames = new ConcurrentDictionary<int, Image>();

    public SizedTifImage(string filename, int width, int height)
    {
        Width = width;
        Height = height;
        _image = Image.FromFile(filename);
        FrameCount = _image.GetFrameCount(FrameDimension.Page);
        ThreadPool.QueueUserWorkItem(ResizeFrame);
    }

    public int FrameCount { get; private set; }
    public int Width { get; private set; }
    public int Height { get; private set; }

    private void ResizeFrame(object state)
    {
        for (int i = 0; i < FrameCount; i++)
        {
            if (_image == null)
                return;

            _image.SelectActiveFrame(FrameDimension.Page, i);
            var bmp = new Bitmap(Width, Height);
            using (var g = Graphics.FromImage(bmp))
            {
                if (_image == null)
                    return;

                g.DrawImage(_image, 0, 0, bmp.Width, bmp.Height);
            }
            _frames.AddOrUpdate(i, bmp, (k, oldValue) => { bmp.Dispose(); return oldValue; });
        }
    }

    public Image GetFrame(int i)
    {
        if (i >= FrameCount)
            throw new IndexOutOfRangeException();

        if (_image == null)
            throw new ObjectDisposedException("Image");

        Image img;
        do
        {
            if (_frames.TryGetValue(i, out img))
                return img;

            Thread.Sleep(10);
        }
        while (true);
    }

    public void Dispose()
    {
        var images = _frames.Values.ToArray();
        _frames.Clear();
        foreach (var img in images)
        {
            img.Dispose();
        }

        if (_image != null)
        {
            _image.Dispose();
            _image = null;
        }
    }